/**
 * Alipay.com Inc.
 * Copyright (c) 2004-2014 All Rights Reserved.
 */
package pay.biz;

import java.util.Date;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.jfinal.log.Logger;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;

import base.model.exception.BizHandleException;
import mt.model.enums.OrderStatusEnum;

/**
 * @Description 交易状态变更通知
 * @Class com.unibroad.touchus.oss.biz.pay.executor.wx.WxTradeNotifyExecutor
 * @author suan@unibroad.com
 * @version V1.0
 */
public class TradeNotifyWxExecutor implements TradeNotifyExecutor {

	private static final Logger LOG = Logger.getLogger(TradeNotifyWxExecutor.class);

	/*
	 * (non-Javadoc) @see
	 * com.unibroad.touchus.oss.biz.apay.executor.NotifyExecutor#execute(java.
	 * util.Map)
	 */
	@Override
	// <xml><appid><![CDATA[wxb73f53be3f9bf83a]]></appid>
	// <bank_type><![CDATA[CFT]]></bank_type>
	// <cash_fee><![CDATA[1]]></cash_fee>
	// <device_info><![CDATA[90014a4841473464040503a24543b14f]]></device_info>
	// <fee_type><![CDATA[CNY]]></fee_type>
	// <is_subscribe><![CDATA[Y]]></is_subscribe>
	// <mch_id><![CDATA[1317868001]]></mch_id>
	// <nonce_str><![CDATA[21708122174066233]]></nonce_str>
	// <openid><![CDATA[o0X2Dt7VKX7ae-mELVUQZK8xct38]]></openid>
	// <out_trade_no><![CDATA[21708122049653556]]></out_trade_no>
	// <result_code><![CDATA[SUCCESS]]></result_code>
	// <return_code><![CDATA[SUCCESS]]></return_code>
	// <sign><![CDATA[B0234ED9DE9A2A64553C4FAC649AB9FB]]></sign>
	// <time_end><![CDATA[20160516154316]]></time_end>
	// <total_fee>1</total_fee>
	// <trade_type><![CDATA[NATIVE]]></trade_type>
	// <transaction_id><![CDATA[4006322001201605165918503016]]></transaction_id>
	// </xml>
	public synchronized void execute(final Map<String, String> notifyDtMap) throws BizHandleException {

		String content = notifyDtMap.get("content");
		Document resultDoc = null;
		try {
			resultDoc = DocumentHelper.parseText(content);
		} catch (DocumentException e) {
			LOG.error("wx notify process failure, xml parse exception, content = " + content, e);
			throw new BizHandleException("wx notify process failure, xml parse exception, content = " + content, e);
		}
		Element rootElement = resultDoc.getRootElement();
		String resultCode = rootElement.elementTextTrim("return_code");
		String tipMsg = rootElement.elementTextTrim("return_msg");

		// 调用返回码
		if (!StringUtils.equalsIgnoreCase(resultCode, "SUCCESS")) {
			LOG.error("wx notify process failure, returnCode=" + resultCode + " ,msg=" + tipMsg);
			throw new BizHandleException("wx notify process failure,return_code error " + resultCode);
		}

		resultCode = rootElement.elementTextTrim("result_code");
		tipMsg = rootElement.elementTextTrim("err_code_des");
		if (!StringUtils.equalsIgnoreCase(resultCode, "SUCCESS")) {
			LOG.error("wx notify process failure, bizCode=" + resultCode + " ,msg=" + tipMsg);
			throw new BizHandleException("wx notify process failure,biz result_code error " + resultCode);
		}

		// 微信支付订单号 1217752501201407033233368018
		String wxTradeNO = rootElement.elementTextTrim("transaction_id");

		// 商户系统的订单号，与请求一致。
		String orderId = rootElement.elementTextTrim("out_trade_no");

		// 支付完成时间，格式为yyyyMMddHHmmss
		String completeTime = rootElement.elementTextTrim("time_end");

		// 获取本地订单
		Record order = Db.findFirst("select * from mt_order where orderId = ? for update", orderId);
		if (order == null) {
			throw new BizHandleException("无法获取订单号!");
		}

		// 本地订单状态
		OrderStatusEnum orderStatus = OrderStatusEnum.getEnumByCode(order.getInt("status"));
		if (orderStatus == OrderStatusEnum.PAY_SUCCESS || orderStatus == OrderStatusEnum.TIMEOUT
				|| orderStatus == OrderStatusEnum.CANCEL || orderStatus == OrderStatusEnum.FINISHED) {
			return;
		}

		// 交易状态
		OrderStatusEnum targetSattus = orderStatus;
		// 当前消息通知中，支付完成时间非空，则视为支付成功，
		if (StringUtils.isNotBlank(completeTime)) {
			targetSattus = OrderStatusEnum.PAY_SUCCESS;
		} else {
			return;
		}

		// 修改订单状态
		boolean success = false;
		if (targetSattus != orderStatus) {
			order.set("updateTime", new Date());
			order.set("tradeNo", wxTradeNO);
			order.set("status", targetSattus.getCode());
			success = Db.update("mt_order", "orderId", order);
		}

		if (!success) {
			// 充值成功，充值业务数据同步失败
			LOG.error("微信充值成功，业务数据同步失败，out_trade_no=" + orderId);
			throw new BizHandleException("微信充值成功，业务数据同步失败，out_trade_no=" + orderId);
		}
	}

}
